import React, { Component } from 'react';
import './index.less';
import { Button, message, Modal } from 'antd';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { actions as tagActions } from '@redux/reducer/tag';
import PropTypes from 'prop-types';
import cn from 'classnames';
import _ from 'lodash';

import DomainSvg from './images/domain.svg';
import TotalSvg from './images/total.svg';
import IpSvg from './images/ip.svg';
import OtherSvg from './images/other.svg';
import FilterSvg from './images/filter.svg';
import AttributeFilter from './components/attribute-flter';
import AssetList from './components/asset-list';
import AssetContent from './components/asset-content';
import AssetSettingModal from './components/asset-setting-modal';
import DetectionTaskModal from './components/detection-task-modal';
import BatchImportModal from './components/batch-import-modal';
import ExportModal from '@components/export-modal';
import StatsFilter from './components/stats-filter';
import CustomAttributeTree from './components/custom-attribute-tree';
import WrapSearch from './components/wrap-search';
import {
  deleteAssetForm,
  deleteAssetReport,
  downloadAssetForm,
  downloadAssetReport,
  getAssetFormList,
  getAssetReportsList
} from '@api/asset';
import { actions as assetManageActions, TreeSelectFilterType } from './reducer';
import { searchNo1DayHelpList, search1DayHelpList } from './assetConstants';
import { actions as authActions } from '@redux/reducer/auth';
import AutoSize from '../../util/useAutoSize';

class AssetManage extends Component {
  static propTypes = {
    setState: PropTypes.func,
    organizationTree: PropTypes.array,
    initAssetManage: PropTypes.func,
    loadOrganizationTree: PropTypes.func,
    loadStaffList: PropTypes.func,
    loadAssetCategoryList: PropTypes.func,
    loadAssetIndustry: PropTypes.func,
    requestLoadAssetStatsCallback: PropTypes.func,
    loadAssets: PropTypes.func,
    exportAssetForm: PropTypes.func,
    exportAssetReport: PropTypes.func,
    currentSelectedSites: PropTypes.array,
    currentAssetCount: PropTypes.number,
    assetSettingModalVisible: PropTypes.bool,
    batchImportModalVisible: PropTypes.bool,
    detectionTaskModalVisible: PropTypes.string,
    exportModalType: PropTypes.string,
    assetStats: PropTypes.object,
    attributeFilter: PropTypes.object,
    loadAssetStats: PropTypes.func,
    cancelLoadAssetStatsCallback: PropTypes.func,
    clearCurrentSelectAndSearch: PropTypes.func,
    search: PropTypes.string,
    loadTags: PropTypes.func,
    modules: PropTypes.array,
    cert: PropTypes.object,
    getCert: PropTypes.func,
    socketIO: PropTypes.object
  };
  constructor(props) {
    super(props);
    this.state = {
      advanceSearchHelpModalVisible: false
    };
  }

  componentDidMount() {
    this.props.initAssetManage();
    this.bindSocketIO();
    this.props.getCert();
    AutoSize('asset-manage-left', 200, '40%');
  }

  componentWillUnmount() {
    //离开当前页面，清除当前勾选资产、筛选、搜索
    this.props.clearCurrentSelectAndSearch();
    // 移除缓存更新事件
    if (this.props.cancelLoadAssetStatsCallback) {
      this.props.cancelLoadAssetStatsCallback();
    }
    this.unbindSocketIO();
  }

  bindSocketIO = () => {
    const { socketIO } = this.props;
    if (!socketIO) {
      return;
    }
    socketIO.on('task_handler', this.onSocketIOData);
  };
  unbindSocketIO = () => {
    const { socketIO } = this.props;
    if (!socketIO) {
      return;
    }
    socketIO.cancel('task_handler', this.onSocketIOData);
  };

  onSocketIOData = data => {
    const { type } = data;
    switch (type) {
      case 'ADD_SCAN_USED_COUNT':
        this.addScanUsedCount();
        break;
      default:
        break;
    }
  };

  addScanUsedCount = () => {
    this.props.getCert();
  };
  getExportModalConfig = () => {
    const {
      exportModalType,
      currentAssetCount,
      currentSelectedSites,
      exportAssetForm,
      exportAssetReport,
      setState
    } = this.props;

    const realSiteCount = currentSelectedSites.length || currentAssetCount;

    let exportModalConfig = {
      assetForm: {
        visible: true,
        target: '资产报表',
        enableRangePick: false,
        onVisibleChange: exportModalType => setState({ exportModalType }),
        listLoader: getAssetFormList,
        downloadDispatcher: () =>
          exportAssetForm().then(res => {
            return _.get(res, 'payload', {});
          }),
        downloader: downloadAssetForm,
        deleter: deleteAssetForm,
        beforeDispatch: () => {
          if (!realSiteCount) {
            message.info('当前筛选项下没有资产结果');
            return false;
          }
          return true;
        }
      },
      assetDoc: {
        visible: true,
        target: '资产报告',
        enableRangePick: false,
        onVisibleChange: exportModalType => setState({ exportModalType }),
        listLoader: getAssetReportsList,
        beforeDispatch: () => {
          if (!realSiteCount) {
            message.info('当前筛选项下没有资产结果');
            return false;
          } else if (realSiteCount > 100) {
            message.info('单次导出的资产报告数上限为100!');
            return false;
          }
          return true;
        },
        downloadDispatcher: () =>
          exportAssetReport().then(res => {
            return _.get(res, 'payload', {});
          }),
        downloader: downloadAssetReport,
        deleter: deleteAssetReport
      }
    };

    return exportModalConfig[exportModalType] || {};
  };

  onSearch = value => {
    this.props.setState({
      search: value,
      // 点击搜索强制刷新
      loadAssetListIndex: Date.now(),
      pagaition: {
        page: 1,
        pageSize: 10
      }
    });
  };

  selectAssetType = (name, key) => {
    const { attributeFilter, setState, loadAssetStats } = this.props;
    if (key === 'total') {
      setState({ attributeFilter: {}, search: '', pagaition: { page: 1, pageSize: 10 } });
      loadAssetStats();
    } else {
      const newAttributeFilter = _.cloneDeep(attributeFilter);
      const preMoreActionValue = _.get(newAttributeFilter, ['moreAction', 'value'], []);
      if (!_.map(preMoreActionValue, 'value').includes('assetType')) {
        newAttributeFilter.moreAction = {
          type: TreeSelectFilterType,
          value: preMoreActionValue.concat({
            label: '资产类型',
            value: 'assetType'
          })
        };
      }

      newAttributeFilter['assetType'] = {
        type: TreeSelectFilterType,
        value: [{ label: name, value: key }]
      };
      setState({
        attributeFilter: newAttributeFilter,
        pagaition: {
          page: 1,
          pageSize: 10
        }
      });
    }
  };

  render() {
    const {
      search,
      batchImportModalVisible,
      detectionTaskModalVisible,
      setState,
      loadOrganizationTree,
      loadStaffList,
      loadAssetCategoryList,
      loadAssetIndustry,
      organizationTree,
      loadAssets,
      requestLoadAssetStatsCallback,
      currentSelectedSites,
      assetStats,
      attributeFilter,
      modules = [],
      cert
    } = this.props;
    const currentSelectedSiteUrlIps = _.filter(
      _.flatten(_.map(currentSelectedSites, site => [site.ipv6 || site.ip, site.url])),
      target => !_.isEmpty(target)
    );
    const currentSelectedSiteIds = _.map(currentSelectedSites, site => site._id);
    const hasOneDayModule = modules.includes('1day');
    const searchHelpList = hasOneDayModule ? search1DayHelpList : searchNo1DayHelpList;
    const assetTypeStats = _.get(assetStats, 'assetType', []);
    const ipCount = _.get(_.find(assetTypeStats, { name: 'ip' }), 'count', 0);
    const domainCount = _.get(_.find(assetTypeStats, { name: 'domain' }), 'count', 0);
    const otherCount = _.get(_.find(assetTypeStats, { name: 'other' }), 'count', 0);

    const summary = [
      {
        icon: TotalSvg,
        name: '全部',
        value: _.get(assetStats, 'count.total', 0),
        key: 'total',
        active: _.isEmpty(attributeFilter)
      },
      { icon: IpSvg, name: 'IP', value: ipCount, key: 'ip' },
      { icon: DomainSvg, name: '网站', value: domainCount, key: 'domain' },
      { icon: OtherSvg, name: '其他', value: otherCount, key: 'other' }
    ];
    const exportModalConfig = this.getExportModalConfig();
    const maxTargetNumber = _.get(cert, 'max_target_number', 0);
    const assetAmount = _.get(cert, 'assetAmount', 0);
    const zoomeyeOrgAssetAmount = _.get(cert, 'zoomeyepro_scan_used_count', 0);
    const proScanCount = _.get(cert, 'zoomeyepro_scan_count', 60000);
    const isScanCount =
      _.get(cert, 'zoomeyepro_scan_count') !== null &&
      _.get(cert, 'zoomeyepro_scan_count') !== -1 &&
      _.get(cert, 'zoomeyepro_scan_used_count') !== null;
    const renderPrompt = (residue, full, value, dom) => {
      return {
        true: (() => {
          return (
            <>
              剩余{residue}：
              <span style={{ color: '#0B6FD6' }}>
                {value}
                {dom}
              </span>
            </>
          );
        })(),
        false: (() => {
          return (
            <span style={{ color: '#FAAD14' }}>
              {full}，目前已达上限{dom}
            </span>
          );
        })()
      }[value > 0 || _.isString(value)];
    };
    return (
      <>
        {_.get(cert, 'is_trial', false) && (
          <div className="asset-prompt">
            {renderPrompt(
              '资产管理数量',
              `系统支持资产管理数量${maxTargetNumber}个`,
              maxTargetNumber - assetAmount,
              ';'
            )}
            &nbsp;
            {renderPrompt(
              '资产扫描次数',
              `系统支持下发${proScanCount}次资产扫描`,
              isScanCount ? proScanCount - zoomeyeOrgAssetAmount : '不限制'
            )}
          </div>
        )}
        <div
          className="asset-manage"
          style={{ height: _.get(cert, 'is_trial', false) ? 'calc(100% - 43px)' : '100' }}
        >
          <div className="asset-manage-left" id="asset-manage-left">
            <div className="asset-manage-left-content">
              <div className="title my-asset-text">我的资产</div>
              <div className="summary">
                {summary.map(({ icon, name, value, key, active }) => (
                  <div
                    className={cn('item', { active })}
                    key={key}
                    onClick={() => this.selectAssetType(name, key)}
                  >
                    <img className="icon" src={icon} alt="" />
                    <span className="name">{name}</span>
                    <span className="value">{value}</span>
                  </div>
                ))}
              </div>
              <CustomAttributeTree />
              <div className="group-filter">
                <div className="title filter-text">过滤筛选</div>
                <StatsFilter />
              </div>
            </div>
          </div>
          <div className="asset-manage-right">
            <div className="search">
              <span className="title">全部</span>
              <img
                className="filter-icon"
                alt=""
                src={FilterSvg}
                onClick={() => this.setState({ advanceSearchHelpModalVisible: true })}
              />
              <WrapSearch value={search} onSearch={this.onSearch} />
            </div>
            <AttributeFilter />
            <div className="assets">
              <AssetList useCallbackGetCert={() => this.props.getCert()} />
              <AssetContent />
            </div>
          </div>
          <AssetSettingModal useCallbackGetCert={() => this.props.getCert()} />
          <DetectionTaskModal
            selectedTargets={currentSelectedSiteUrlIps}
            selectedTargetsIds={currentSelectedSiteIds}
            visible={detectionTaskModalVisible}
            onVisibleChange={key => setState({ detectionTaskModalVisible: key })}
            onSuccess={() => setState({ detectionTaskModalVisible: '' })}
          />
          <BatchImportModal
            visible={batchImportModalVisible}
            onClose={() => setState({ batchImportModalVisible: false })}
            afterSuccess={(allRight = true) => {
              loadAssets();
              loadAssetCategoryList();
              loadAssetIndustry();
              loadOrganizationTree();
              loadStaffList();
              requestLoadAssetStatsCallback();
              this.props.getCert();
              this.props.loadTags();
              if (allRight) {
                setState({ batchImportModalVisible: false });
              }
            }}
            organizationTree={organizationTree}
            onOrgPopupVisibleChange={visible => visible && loadOrganizationTree()}
          />
          <ExportModal {...exportModalConfig} />
          <Modal
            maskClosable={false}
            title="查询语法参考"
            visible={this.state.advanceSearchHelpModalVisible}
            onCancel={() => this.setState({ advanceSearchHelpModalVisible: false })}
            className={cn('no-header-bottom-lines', 'bottom-center', 'padding-24')}
            footer={[
              <Button
                type="primary"
                key="0"
                onClick={() => this.setState({ advanceSearchHelpModalVisible: false })}
              >
                确定
              </Button>
            ]}
          >
            <div className="aml-c-operations-search-help-list">
              <p className="direct">
                在搜索框直接输入关键词，系统会从资产名称、URL、IP、部门、端口、操作系统、服务、组件、防护设备、标题、行业、运营商、ASN、组织进行搜索。您也可以尝试以下语法进行更精准的搜索：
              </p>
              {searchHelpList.map((item, index) => (
                <p key={index} className="search-item">
                  {index + 1}) {item}
                </p>
              ))}
              <div className="advance">
                <p>高级搜索: 可以使用 &amp;&amp; 或者 || 符号，例如</p>
                <p>
                  1) 与：ip=&quot;192.12.2.&quot; &amp;&amp; service=&quot;ssl&quot; &amp;&amp;
                  component=&quot;apache httpd&quot;
                </p>
                <p>2) 或：service=&quot;cisco&quot; || component=&quot;cisco&quot;</p>
                <br />
                <p>精准匹配和模糊匹配：</p>
                <p>1) 精准匹配为查询值与目标值完全相等才命中；模糊匹配为目标值包含查询值就命中</p>
                <p>
                  2)
                  port、origin、vulLevel、pingable、portful默认且只有精准匹配。其它字段默认为模糊匹配，如需切换成精准匹配，需要在搜索语句前加上&quot;exact:&quot;，例如：exact:ip=&quot;192.12.2.1&quot;
                </p>
              </div>
            </div>
          </Modal>
        </div>
      </>
    );
  }
}

const mapStateToProps = state => {
  return {
    assetSettingModalVisible: _.get(state, 'assetManage.assetSettingModalVisible', false),
    batchImportModalVisible: _.get(state, 'assetManage.batchImportModalVisible', false),
    detectionTaskModalVisible: _.get(state, 'assetManage.detectionTaskModalVisible', ''),
    exportModalType: _.get(state, 'assetManage.exportModalType', false),
    organizationTree: _.get(state, 'assetManage.organizationTree', []),
    currentAssetCount: _.get(state, 'assetManage.currentAssetCount', 0),
    currentSelectedSites: _.get(state, 'assetManage.currentSelectedSites', []),
    assetStats: _.get(state, 'assetManage.assetStats', {}),
    attributeFilter: _.get(state, 'assetManage.attributeFilter', {}),
    search: _.get(state, 'assetManage.search', {}),
    modules: _.get(state, 'auth.cert.modules', []),
    cert: _.get(state, 'auth.cert', {}),
    socketIO: _.get(state, 'socketIO.socketIO', null)
  };
};

const mapDispatchToProps = dispatch => {
  return {
    ...bindActionCreators(assetManageActions, dispatch),
    ...bindActionCreators(tagActions, dispatch),
    ...bindActionCreators(authActions, dispatch)
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(AssetManage);
